#ifndef CALL_LIST__
#define CALL_LIST__

#include "area.h"

/** Zakladni trida udrzujici poradi vysilacu cekajicich na prirazeni frekvenci.
 * Na zacatku dostane serazene vysilace, pote je vraci ve stejne poradi.
 * Dale pocita sirku vyuziteho frekvenciho pasma.
 */
class CallList {
public:
	/** Defaultni konstruktor.
	 * \param a mapa problemu
	 * \param f maximalni pocet pouzitych frekvenci
	 * \param ordering pocatecni setrideni vysilacu
	 */
	CallList(Area * a, int f, int * ordering = NULL): area(a), frequencies(f) {
		if (ordering != NULL) initialize(ordering);
	}
	/** Destruktor, nema zadnou praci.
	 */
	virtual ~CallList() {}
	/** Vrati sirku vyuziteho frekvencniho pasma.
	 * \return sirka frekvencniho pasma
	 */
	int getSpan() {
		return span;
	}
	/** Vrati index aktualniho vysilace.
	 * \return index vysilace na aktualni pozici v seznamu 
	 */
	int getCurrent() {
		if (position > -1 && position < area->size)	return ordering[position];
		else return -1;
	}
	virtual void initialize(int * ordering);
	virtual void assign(int f); ///< Assigns call to the last selected call
	virtual bool getNext();	///< Loads the next call (if any)
protected:
	Area * area; ///< mapa problemu
	int frequencies; ///< maximalni pocet frekvenci
	int position; ///< aktualni pozice v seznamu
	int span; ///< sirka vyuziteho frekvencniho pasma
	int * ordering; ///< setrideni vysilacu
};

/** Specializovana trida preusporadavajici vysilace v seznamu podle aktualni situace.
 * Preusporadavani se provadi algoritmem Generalized Saturation Degree vzdy po prirazeni
 * frekvence. Uprednostnovany jsou vysilace, ktere maji hodne zablokovanych frekvenci.
 */
class GSDCallList: public CallList {
public:
	/** Defaultni konstruktor. Alokuje potrebne pomocne datove struktury nutne k 
	 * rychlemu preusporadavani seznamu vysilacu.
	 * \param a mapa problemu
	 * \param f maximalni pocet pouzitych frekvenci
	 * \param ordering pocatecni poradi setridenych vysilacu, algoritmus jej bude menit
	 */
	GSDCallList(Area * a, int f, int * ordering = NULL): CallList(a, f, ordering) {
		call_degree = new int[area->size];
		degrees = new int[area->size * frequencies];
		init_position = new int[area->size];
		if (ordering != NULL) initialize(ordering);
	}
	/** Destruktor odalokovava pouzite datove strukury.
	 */
	virtual ~GSDCallList() {
		delete[] call_degree;
		delete[] degrees;
		delete[] init_position;
	}
	void initialize(int * ordering);
	void assign(int f);
	bool getNext();
private:
	int * degrees; ///< pole udrzujici vliv jednotlivych zakazanych frekvenci na vysilace
	int * call_degree; ///< celkove stupne vysilacu, stupen = soucet vlivu vsech zakazanych frekvenci na vysilac
	int * init_position; ///< poradi vysilacu v prvotnim setrideni
};

#endif
